LoginSignup
189
149

More than 1 year has passed since last update.

pandas.DataFrameに1行ずつ書き足す早い方法を調べた

Last updated at Posted at 2018-11-07

何故やったか

pandas.DataFrameに1行ずつデータを書き出して行く処理を書いていたんですが、10万行ほど書き出すと結構遅くなっちゃいました。今後行数が増える予定なので、これを期にどう書くと早くなるか確認しておく事にしました。

やったこと

  1. pandas.DataFrame.iloc[i, j] = hoge で1つずつ記入
  2. pandas.DataFrame.append(hoge) で1行まとめて追加
  3. pandas.DataFrame.iloc[i,:] = hoge で1行まとめて追加
  4. 1列ずつリストで作ってDataFrameに変換する※ ※ 2018.11/12 kishiyamaさんに教えて頂いたやり方を追記

試した環境

windows10 64bit
cpu: Ryzen7 1700X
gpu: GTX1080Ti
python3.6
jupyter 1.0.0
jupyter-client 5.2.3
jupyter-console 6.0.0
jupyter-core 4.4.0
Microsoft Edge 17.17134

結論

1列ずつリストで作ってDataFrameに変換するやり方がメチャメチャ速い!
df.iloc[i, :] = listまたは df.iloc[i, :] = numpy.array が速い
※ 2018.11/12 kishiyamaさんに教えて頂いたやり方がめっちゃ速いので修正
image.png

コードと実行結果

1. pd.DataFrame.iloc[i, j] = hoge で1つずつ記入
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'], index=range(100))

    for i in range(100):
        log.iloc[i,0] = 'test'
        log.iloc[i,1] = ''
        log.iloc[i,2] = ''
        log.iloc[i,3] = 'test'
        log.iloc[i,4] = 'test'
    return(log)

%timeit log = test()

88.3 ms ± 2.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

遅い

2-1. pd.DataFrame.append(hoge) で1行まとめて追加 (pandas.DataFrame)
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'])

    for _ in range(100):
        addRow = pd.DataFrame(['test','','','test','test'], index=log.columns).T
        log = log.append(addRow)

    return(log)

%timeit log = test()

59.6 ms ± 1.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

ちょっと速くなった

2-2. pd.DataFrame.append(hoge) で1行まとめて追加 (pandas.Series)
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'])

    for _ in range(100):
        addRow = pd.Series(['test','','','test','test'], index=log.columns)
        log = log.append(addRow, ignore_index=True)

    return(log)

%timeit log = test()

131 ms ± 3.96 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

逆に遅くなっちゃう

3-1. pandas.DataFrame.iloc[i,:] = hoge で1行まとめて追加 (pandas.Series)
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'], index=range(100))

    for i in range(100):
        addRow = pd.Series(['test','','','test','test'])
        log.iloc[i,:] = addRow

    return(log)

%timeit log = test()

70.4 ms ± 2.33 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
3-2. pandas.DataFrame.iloc[i,:] = hoge で1行まとめて追加 (numpy.array)
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'], index=range(100))

    for i in range(100):
        addRow = np.array(['test','','','test','test'])
        log.iloc[i,:] = addRow

    return(log)

%timeit log = test()

20.1 ms ± 108 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

速い

3-3. pandas.DataFrame.iloc[i,:] = hoge で1行まとめて追加 (list)
def test():
    log = pd.DataFrame([], columns=['A','B','C','D','E'], index=range(100))

    for i in range(100):
        addRow = ['test','','','test','test']
        log.iloc[i,:] = addRow
    return(log)

%timeit log = test()

19.8 ms ± 216 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

速い

4. 1列ずつリストで作ってDataFrameに変換する
def test():
    a = []
    b = []
    c = []
    d = []
    e = []

    for i in range(100):
        a += ['test']
        b += ['']
        c += ['']
        d += ['test']
        e += ['test']

    return pd.DataFrame(
        data={'A': a, 'B': b, 'C': c, 'D': d, 'E': e},
        columns=['A', 'B', 'C', 'D', 'E']
    )
%timeit log = test()

1.58 ms ± 18.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

めっちゃ速

というわけで、リストで足し合わせておいてpd.DataFrame()に変換するやり方がめっちゃ速です。以前やってたやり方より50倍速いので、前回3日待った処理が1時間ちょいで完了できそう!

189
149
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
189
149